package me.youline.dataServer.controller;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import me.youline.dataServer.ConfigConstants;
import me.youline.dataServer.controller.dto.IdPaginationDTO;
import me.youline.dataServer.controller.dto.PubMsgBaseFrontDTO;
import me.youline.dataServer.controller.dto.PubMsgDetailFrontDTO;
import me.youline.dataServer.controller.dto.PubMsgPostDTO;
import me.youline.dataServer.controller.dto.PubMsgStatusDTO;
import me.youline.dataServer.entity.PubMsgStatisticRecorder;
import me.youline.dataServer.entity.PublicMessage;
import me.youline.dataServer.entity.PublicMessageIndex;
import me.youline.dataServer.entity.UserToken;
import me.youline.dataServer.exception.UnExistDataException;
import me.youline.dataServer.exception.UnPermitAccessException;
import me.youline.dataServer.service.MimeConfig;
import me.youline.dataServer.service.PubMsgRecorderService;
import me.youline.dataServer.service.authentication.UserTokenService;
import me.youline.dataServer.service.front.IdPageDTOAdapter;
import me.youline.dataServer.service.front.PubMsgStatusDTOAdapter;
import me.youline.dataServer.service.front.PublicMessageDTOAdapter;
import me.youline.dataServer.service.front.SocialRelationDTOAdapter;
import me.youline.dataServer.service.front.UserInfoDTOAdapter;
import me.youline.dataServer.service.pubMsg.PublicMessageFacade;
import me.youline.dataServer.service.support.MsgBuilder;
import me.youline.dataServer.utils.IdPagination;
import me.youline.dataServer.utils.ResponseTypeOutputUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;

/**
 * 公告消息业务控制器
 * @author linhan
 *
 */
@Controller
@RequestMapping("/pubmsg")
public class PublicMessageController {

	@Autowired
	private UserTokenService tokenService;

	@Autowired
	private PublicMessageFacade publicMessageFacade;


	@Autowired
	private PublicMessageDTOAdapter msgAssembler;
	@Autowired
	private UserInfoDTOAdapter userInfoAssembler;

	@Autowired
	private PubMsgRecorderService recorderService;
	
	@Autowired
	private PubMsgStatusDTOAdapter statusDTOAdapter;

	@Autowired
	private SocialRelationDTOAdapter socialRelationAssembler;

	private Logger logger = LoggerFactory
			.getLogger(PublicMessageController.class);

	/**
	 * 创建公告
	 * 
	 * @param token
	 * @param postDTO
	 * @param fileRequest
	 * @param request
	 * @param response
	 */
	
	@RequestMapping(method = RequestMethod.POST)
	public void buildPublicMessage(
			@RequestParam(value = ConfigConstants.REQ_PARAM_APP_TOKEN_NAME) String token,
			@Valid PubMsgPostDTO postDTO, BindingResult result,
			MultipartRequest fileRequest, HttpServletRequest request,
			HttpServletResponse response) {
		try {
			if (result.hasErrors()) {
				response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
				String res = MsgBuilder.error().errorCode("200306")
						.errorMsg("提交的消息字段检验不符合要求")
						.reqUrl(request.getRequestURI()).toJSONString();
				ResponseTypeOutputUtils.renderJson(response, res);
				return;
			}
			UserToken userTokenInfo = tokenService
					.getUserTokenByTokenStr(token);
			MultipartFile recognPicFile = fileRequest.getFile("recognPic");
		    MultipartFile displayImg = fileRequest.getFile("displayPic");
			if (!isLegalMsgFile(recognPicFile, displayImg)) {
				response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
				ResponseTypeOutputUtils.renderJson(response, MsgBuilder.error()
						.errorCode("200301").errorMsg("公告文件不符合要求")
						.toJSONString());
				return;
			}
			PublicMessage msg = publicMessageFacade.buildOriginalPublicMessage(
					userTokenInfo.getUserId(), postDTO, getFileStream(recognPicFile),
					getFileStream(displayImg));
			response.setStatus(HttpServletResponse.SC_CREATED);
			ResponseTypeOutputUtils.renderJson(response, MsgBuilder.success()
					.addObj("msgId", msg.getId()).addObj("publishTime", msg.getPublishTime()).toJSONString());
			return;
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			ResponseTypeOutputUtils.renderJson(response, MsgBuilder.error()
					.errorCode("100001").errorMsg("创建原创消息业务执行失败")
					.toJSONString());
			return;
		}
	}
	
	private InputStream getFileStream(MultipartFile file) throws IOException{
		return file == null ? null: file.getInputStream();
	}

	/**
	 * 检验是否为合法的消息文件
	 * @param postDTO
	 * @param recognPicFile
	 * @param displayPicFile
	 * @return
	 */
	private boolean isLegalMsgFile(MultipartFile recognPicFile, MultipartFile displayPicFile) {
		if(recognPicFile == null || displayPicFile == null){
			return false;
		}
		if(displayPicFile != null){//展示图需要进行格式验证
			if (MimeConfig.ALLOW_IMAGE_TYPE.contains(displayPicFile
					.getContentType())) {
				return true;
			}
		}
		if(recognPicFile != null){
			if (MimeConfig.ALLOW_IMAGE_TYPE.contains(recognPicFile
					.getContentType())) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 删除公告
	 * 
	 * @param token
	 * @param msgId
	 * @param response
	 */
	@RequestMapping(value = "/{msgId}", method = RequestMethod.DELETE)
	public void deleteMessage(
			@RequestParam(value = ConfigConstants.REQ_PARAM_APP_TOKEN_NAME) String token,
			@PathVariable Long msgId, HttpServletResponse response) {
		UserToken userTokenInfo = tokenService.getUserTokenByTokenStr(token);
		try {
			publicMessageFacade.deletePublicMessage(msgId,
					userTokenInfo.getUserId());
			response.setStatus(HttpServletResponse.SC_OK);
			ResponseTypeOutputUtils.renderJson(response, MsgBuilder.success()
					.toJSONString());
		} catch (UnExistDataException e) {
			response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
			ResponseTypeOutputUtils.renderJson(response, MsgBuilder.error()
					.errorCode("200304").errorMsg("执行的消息不存在").toJSONString());
		} catch (UnPermitAccessException e) {
			response.setStatus(HttpServletResponse.SC_FORBIDDEN);
			ResponseTypeOutputUtils.renderJson(response, MsgBuilder.error()
					.errorCode("100002").errorMsg("当前用户无权限操作").toJSONString());
		} catch (Exception e) {
			logger.error(e.getMessage(),e);
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			ResponseTypeOutputUtils.renderJson(response, MsgBuilder.error()
					.errorCode("100001").errorMsg("删除消息业务执行失败").toJSONString());
		}
		return;
	}

	

	/**
	 * 获取消息点赞数
	 * 
	 * @param token
	 * @param originId
	 * @param response
	 */
	@RequestMapping(value = "/{msgId}/statistic",method=RequestMethod.GET)
	public void getMsgRecorder(
			@RequestParam(value = ConfigConstants.REQ_PARAM_APP_TOKEN_NAME) String token,
			@PathVariable Long msgId, HttpServletResponse response) {
		try {
			PubMsgStatisticRecorder r = recorderService.getPubMsgStatisticRecorder(msgId);
			if(r == null){
				r = new PubMsgStatisticRecorder();
				r.setMessageId(msgId);
				r.setPraiseNum(0);
			}
			String res = MsgBuilder.success()
					.addObj("msgId", r.getMessageId())
					.addObj("praiseNum", r.getPraiseNum()).toJSONString();
			response.setStatus(HttpServletResponse.SC_OK);
			ResponseTypeOutputUtils.renderJson(response, res);
			return;
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			ResponseTypeOutputUtils
					.renderJson(response, MsgBuilder.error()
							.errorCode("100001").errorMsg("获取点赞数失败")
							.toJSONString());
		}
	}


	/**
	 * 获取个人主页列表消息数据
	 * 
	 * @param userId
	 * @param token
	 * @param idPaginationDTO
	 * @param res
	 */
	@RequestMapping(value = "/personal/{userId}", method = RequestMethod.GET)
	public void getPersonHomepageMsg(
			@PathVariable Long userId,
			@RequestParam(value = ConfigConstants.REQ_PARAM_APP_TOKEN_NAME) String token,
			@ModelAttribute IdPaginationDTO idPaginationDTO,
			HttpServletResponse res) {
		try {
			UserToken userTokenInfo = tokenService
					.getUserTokenByTokenStr(token);
			IdPagination p = IdPageDTOAdapter.getPagination(idPaginationDTO);
			List<PublicMessageIndex> msgList = publicMessageFacade
					.getPersonalHomepageMsgList(userTokenInfo.getUserId(),userId, p);
			List<PubMsgBaseFrontDTO> msgDTOList = msgAssembler.getPubMsgBaseFrontDTOs(msgList);
			res.setStatus(HttpServletResponse.SC_OK);
			ResponseTypeOutputUtils.renderJson(res, MsgBuilder.success().addObj("pubList", msgDTOList).toJSONString());
			return;
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			ResponseTypeOutputUtils.renderJson(res, MsgBuilder.error()
					.errorCode("100001").errorMsg("获取个人主页信息消息业务执行失败")
					.toJSONString());
			return;
		}
	}

	/**
	 * 获取广场列表数据
	 * 
	 * @param token
	 * @param idPaginationDTO
	 * @param res
	 */
	@RequestMapping(value = "/square/list", method = RequestMethod.GET)
	public void getSquareAreaMsg(
			@RequestParam(value = ConfigConstants.REQ_PARAM_APP_TOKEN_NAME) String token,
			@ModelAttribute IdPaginationDTO idPaginationDTO,
			HttpServletResponse res) {
		try {
			List<PublicMessageIndex> pubMsgs = publicMessageFacade
					.getSquareMsgList(IdPageDTOAdapter.getPagination(idPaginationDTO));
			List<PubMsgBaseFrontDTO> msgDTOList = msgAssembler.getPubMsgBaseFrontDTOs(pubMsgs);
			res.setStatus(HttpServletResponse.SC_OK);
			ResponseTypeOutputUtils.renderJson(res, MsgBuilder.success().addObj("pubList", msgDTOList).toJSONString());
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			ResponseTypeOutputUtils.renderJson(res, MsgBuilder.error()
					.errorCode("100001").errorMsg("获取广场列表业务执行失败")
					.toJSONString());
			return;
		}
	}
	
	
	/**
	 * 获取关注人列表数据
	 * 
	 * @param token
	 * @param idPaginationDTO
	 * @param res
	 */
	@RequestMapping(value = "/following/list", method = RequestMethod.GET)
	public void getFollowingMsg(
			@RequestParam(value = ConfigConstants.REQ_PARAM_APP_TOKEN_NAME) String token,
			@ModelAttribute IdPaginationDTO idPaginationDTO,
			HttpServletResponse res) {
		try {
			UserToken userTokenInfo = tokenService
					.getUserTokenByTokenStr(token);
			List<PublicMessage> pubMsgs = publicMessageFacade
					.getFollowingMsgList(userTokenInfo.getUserId(),IdPageDTOAdapter.getPagination(idPaginationDTO));
			List<PubMsgDetailFrontDTO> msgDTOList = msgAssembler.getPubMsgDetailFrontDTOs(userTokenInfo.getUserId(), (pubMsgs));
			res.setStatus(HttpServletResponse.SC_OK);
			ResponseTypeOutputUtils.renderJson(res, MsgBuilder.success().addObj("pubList", msgDTOList).toJSONString());
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			ResponseTypeOutputUtils.renderJson(res, MsgBuilder.error()
					.errorCode("100001").errorMsg("获取关注人公告列表业务执行失败")
					.toJSONString());
			return;
		}
	}
	
	
	/**
	 * 获取指定消息最新状态信息
	 * @param msgIds
	 * @param token
	 * @param res
	 */
	@RequestMapping(value = "/status", method = RequestMethod.GET)
	public void getMsgStatusList(@RequestParam Long[] msgIds,@RequestParam(value = ConfigConstants.REQ_PARAM_APP_TOKEN_NAME) String token, HttpServletResponse res){
		try {
			UserToken userTokenInfo = tokenService
					.getUserTokenByTokenStr(token);
			List<PubMsgStatusDTO> list = statusDTOAdapter.getMsgStatusDTOList(userTokenInfo.getUserId(), Arrays.asList(msgIds));
			res.setStatus(HttpServletResponse.SC_OK);
			ResponseTypeOutputUtils.renderJson(res,MsgBuilder.success().addObj("msgListStatus", list).toJSONString());
			return;
		} catch (Exception e) {
			ResponseTypeOutputUtils.renderJson(res, MsgBuilder.error()
					.errorCode("100001").errorMsg("获取公告列表状态失败")
					.toJSONString());
			return;
		} 
	
	}
	
	/**
	 * 获取公告详细数据
	 * @param msgId 消息ID
	 * @param token 用户token
	 * @param response
	 */
	@RequestMapping(value= "/detail/{msgId}",  method=RequestMethod.GET)
	public void getPubMsgDetailInfo(@PathVariable Long msgId ,@RequestParam(value = ConfigConstants.REQ_PARAM_APP_TOKEN_NAME) String token, HttpServletResponse response){
		UserToken userToken = tokenService.getUserTokenByTokenStr(token);
		try {
			PublicMessage msg = publicMessageFacade.getPublicMessageDetailInfo(userToken.getUserId(), msgId);
			PubMsgDetailFrontDTO dto = msgAssembler.getPubMsgDetailDTO(userToken.getUserId(), msg);
			response.setStatus(HttpServletResponse.SC_OK);
			ResponseTypeOutputUtils.renderJson(response,MsgBuilder.success().addObj("msg", dto).toJSONString());
		}catch(UnPermitAccessException e){
			response.setStatus(HttpServletResponse.SC_FORBIDDEN);
			ResponseTypeOutputUtils.renderJson(response,MsgBuilder.error().errorCode("200309").errorMsg("无权限访问指定的消息及其资源").toJSONString());
		}catch(UnExistDataException e){
			response.setStatus(HttpServletResponse.SC_NOT_FOUND);
			ResponseTypeOutputUtils.renderJson(response,MsgBuilder.error().errorCode("200304").errorMsg("执行的消息不存在").toJSONString());
		}catch(Exception e){
			logger.error(e.getMessage(),e);
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			ResponseTypeOutputUtils.renderJson(response,MsgBuilder.error().errorCode("100001").errorMsg("获取公告栏消息详细数据异常").toJSONString());
		}
	}

}
